import Type from "./Type.js";
import { LayerType } from "./Type.js"
export default class Db {
    constructor() {
        if (Db.instance) {
            return Db.instance;
        }
        Db.instance = this;
    }

    open() {
        return new Promise((resolve, reject) => {
            const connection = window.indexedDB.open("valkyrja", 1)
            connection.onsuccess = function (event) {
                resolve(event.target.result);
            }

            connection.onupgradeneeded = function (event) {
                const db = event.target.result;

                const metas = db.createObjectStore(Type.Meta, { keyPath: "id" });
                metas.createIndex("name", "name", { unique: false });
                metas.createIndex("meta_id", "meta_id", { unique: false });

                const layers = db.createObjectStore(Type.Layer, { keyPath: "id" });
                layers.createIndex("meta_id", "meta_id", { unique: false });

                const inserts = db.createObjectStore(Type.Insert, { keyPath: "id" });
                inserts.createIndex("layer", "layer", { unique: false });
                inserts.createIndex("insert_id", "insert_id", { unique: false });
                inserts.createIndex("meta_id", "meta_id", { unique: false });

                const lwpolylines = db.createObjectStore(Type.LWPolyline, { keyPath: "id" });
                lwpolylines.createIndex("layer", "layer", { unique: false });
                lwpolylines.createIndex("meta_id", "meta_id", { unique: false });

                const lines = db.createObjectStore(Type.Line, { keyPath: "id" });
                lines.createIndex("layer", "layer", { unique: false });
                lines.createIndex("meta_id", "meta_id", { unique: false });

                const circles = db.createObjectStore(Type.Circle, { keyPath: "id" });
                circles.createIndex("layer", "layer", { unique: false });
                circles.createIndex("meta_id", "meta_id", { unique: false });

                const texts = db.createObjectStore(Type.Text, { keyPath: "id" });
                texts.createIndex("layer", "layer", { unique: false });
                texts.createIndex("meta_id", "meta_id", { unique: false });

                const mtexts = db.createObjectStore(Type.MText, { keyPath: "id" });
                mtexts.createIndex("layer", "layer", { unique: false });
                mtexts.createIndex("meta_id", "meta_id", { unique: false });

                const arcs = db.createObjectStore(Type.Arc, { keyPath: "id" });
                arcs.createIndex("layer", "layer", { unique: false });
                arcs.createIndex("meta_id", "meta_id", { unique: false });

                const splines = db.createObjectStore(Type.SPLine, { keyPath: "id" });
                splines.createIndex("layer", "layer", { unique: false });
                splines.createIndex("meta_id", "meta_id", { unique: false });

                const polylines = db.createObjectStore(Type.Polyline, { keyPath: "id" });
                polylines.createIndex("layer", "layer", { unique: false });
                polylines.createIndex("meta_id", "meta_id", { unique: false });

                const ellipses = db.createObjectStore(Type.Ellipse, { keyPath: "id" });
                ellipses.createIndex("layer", "layer", { unique: false });
                ellipses.createIndex("meta_id", "meta_id", { unique: false });

                const hatches = db.createObjectStore(Type.Hatch, { keyPath: "id" });
                hatches.createIndex("layer", "layer", { unique: false });
                hatches.createIndex("meta_id", "meta_id", { unique: false });

                const modifys = db.createObjectStore(Type.Modify, { keyPath: "id" });
                modifys.createIndex("layer", "layer", { unique: false });
                modifys.createIndex("meta_id", "meta_id", { unique: false });

                const tracks = db.createObjectStore(Type.Track, { keyPath: "id" });
                tracks.createIndex("meta_id", "meta_id", { unique: false });
                tracks.createIndex("type", "type", { unique: false });

                const positions = db.createObjectStore(Type.Position, { keyPath: "id" });
                positions.createIndex("meta_id", "meta_id", { unique: false });

                const vehicles = db.createObjectStore(Type.Vehicle, { keyPath: "id" });
                vehicles.createIndex("meta_id", "meta_id", { unique: false });

                const persons = db.createObjectStore(Type.Person, { keyPath: "id" });
                persons.createIndex("meta_id", "meta_id", { unique: false });

                const devices = db.createObjectStore(Type.Device, { keyPath: "id" });
                devices.createIndex("meta_id", "meta_id", { unique: false });

                const warnings = db.createObjectStore(Type.Warning, { keyPath: "id" });
                warnings.createIndex("meta_id", "meta_id", { unique: false });

                const sensors = db.createObjectStore(Type.Sensor, { keyPath: "id" });
                sensors.createIndex("meta_id", "meta_id", { unique: false });

                const SMVentilate = db.createObjectStore(LayerType.SMVentilate, { keyPath: "id" });
                SMVentilate.createIndex("meta_id", "meta_id", { unique: false });

            }

            connection.onerror = function (err) {
                reject(err);
            }
        })
    }

    async operation(store, type, data) {
        const types = ['add', 'get', 'getAll', 'put', 'delete'];
        if (!types.includes(type)) {
            throw new Error(`操作类型错误, 仅支持: ${types.toString()} 方法`);
        }
        let readType = 'readonly'
        if (type === "add" || type === "put" || type === "delete") {
            readType = 'readwrite';
        }
        const res = await this.open();
        const objectStore = res.transaction(store, readType).objectStore(store);
        return new Promise((resolve, reject) => {
            const request = objectStore[type](data);
            request.onsuccess = (res) => {
                resolve(res.target.result);
            }
            request.onerror = (err) => {
                reject(err);
            }
        })
    }

    async index(store, name, data) {
        const res = await this.open();
        const objectStore = res.transaction(store, 'readwrite').objectStore(store);
        const index = objectStore.index(name);
        const request = index.getAll(data);
        return new Promise((resolve, reject) => {
            request.onsuccess = (res) => {
                resolve(res.target.result);
            }
            request.onerror = (err) => {
                reject(err);
            }
        })
    }

    async init(data) {
        window.indexedDB.deleteDatabase("valkyrja");
        await this.refresh(Type.Device, data.entities.devices);
    }

    async refreshMeta(meta) {
        const res = await this.open();
        const metasStore = res.transaction(Type.Meta, 'readwrite').objectStore(Type.Meta);
        metasStore.clear();
        metasStore.add(meta);
    }

    async refresh(name, vectors) {
        const res = await this.open();
        const store = res.transaction(name, 'readwrite').objectStore(name);
        store.clear();
        vectors.forEach((item) => store.add(item));
    }

    async clear(meteId) {
        const res = await this.open();
        Object.keys(Type).map(key => {
            const store = Type[key];
            if (store === Type.RootPolygon || store === Type.Measure || store === Type.slightPoint) {
                return;
            }

            const objectStore = res.transaction(store, 'readwrite').objectStore(store);
            const index = objectStore.index("meta_id");
            index.getAll(meteId).onsuccess=function(e){
                const items = e.target.result;
                for (const item of items) {
                    objectStore.delete(item.id);
                }
            };
        });
    }
}
